package com.my.auth.service.service.impl;

import cn.dev33.satoken.secure.SaSecureUtil;
import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
import com.alibaba.nacos.shaded.com.google.gson.Gson;
import com.my.auth.common.enums.AuthUserStatusEnum;
import com.my.auth.common.enums.IsDeletedFlagEnum;
import com.my.auth.service.dao.*;
import com.my.auth.service.entity.*;
import com.my.auth.service.service.AuthUserService;
import com.my.auth.utils.RedisUtil;
import jakarta.annotation.Resource;
import lombok.SneakyThrows;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * (AuthUser)表服务实现类
 *
 * @author makejava
 * @since 2023-11-01 01:25:23
 */
@Service("authUserService")
public class AuthUserServiceImpl implements AuthUserService {
    @Resource
    private AuthUserDao authUserDao;
    @Resource
    private AuthRolePermissionDao authRolePermissionDao;
    @Resource
    private AuthPermissionDao authPermissionDao;
    @Resource
    private AuthRoleDao authRoleDao;
    @Resource
    private AuthUserRoleDao authUserRoleDao;

    private static final String salt = "chicken";

    private static final String authPermissionPrefix = "auth.permission";

    private static final String authRolePrefix = "auth.role";

    private static final String LOGIN_PREFIX = "loginCode";

    @Override
    @SneakyThrows
    @Transactional(rollbackFor = Exception.class)
    public Boolean register(AuthUser authUser) {
        //校验用户是否存在
        AuthUser existAuthUser = new AuthUser();
        existAuthUser.setUserName(authUser.getUserName());
        List<AuthUser> existUser = authUserDao.queryAllByLimit(existAuthUser);
        if (!existUser.isEmpty()) {
            return true;
        }
        if (StringUtils.isNotBlank(authUser.getPassword())) {
            authUser.setPassword(SaSecureUtil.md5BySalt(authUser.getPassword(), salt));
        }
        authUser.setStatus(AuthUserStatusEnum.OPEN.getCode());
        authUser.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getCode());
        int count = authUserDao.insert(authUser);

        //建立一个初步的角色的关联
        AuthRole authRole = new AuthRole();
        authRole.setRoleKey("normal_user");
        AuthRole roleResult = authRoleDao.queryAllByLimit(authRole);
        Long roleId = roleResult.getId();
        Long userId = authUser.getId();
        AuthUserRole authUserRole = new AuthUserRole();
        authUserRole.setUserId(userId);
        authUserRole.setRoleId(roleId);
        authUserRole.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getCode());
        authUserRoleDao.insert(authUserRole);

        String roleKey = RedisUtil.buildKey(authRolePrefix, authUser.getUserName());
        List<AuthRole> roleList = new LinkedList<>();
        roleList.add(authRole);
        RedisUtil.set(roleKey, new Gson().toJson(roleList));

        AuthRolePermission authRolePermission = new AuthRolePermission();
        authRolePermission.setRoleId(roleId);
        List<AuthRolePermission> rolePermissionList = authRolePermissionDao.
                queryAllByLimit(authRolePermission);

        List<Long> permissionIdList = rolePermissionList.stream()
                .map(AuthRolePermission::getPermissionId).collect(Collectors.toList());
        //根据roleId查权限
        List<AuthPermission> permissionList = authPermissionDao.queryByRoleList(permissionIdList);
        String permissionKey = RedisUtil.buildKey(authPermissionPrefix, authUser.getUserName());
        RedisUtil.set(permissionKey, new Gson().toJson(permissionList));

        return count > 0;
    }

    @Override
    public Boolean update(AuthUser authUser) {
        Integer count = authUserDao.updateByUserName(authUser);
        return count > 0;
    }

    @Override
    public Boolean delete(AuthUser authUser) {
        authUser.setIsDeleted(IsDeletedFlagEnum.DELETED.getCode());
        int count = authUserDao.update(authUser);
        //有任何的更新，都要与缓存进行同步的修改
        return count > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public SaTokenInfo doLogin(String validCode) {
        String loginKey = RedisUtil.buildKey(LOGIN_PREFIX, validCode);
        String openId = RedisUtil.get(loginKey);
        if (StringUtils.isBlank(openId)) {
            return null;
        }
        AuthUser authUser = new AuthUser();
        authUser.setUserName(openId);
        this.register(authUser);
        StpUtil.login(openId);
        return StpUtil.getTokenInfo();
    }

    @Override
    public AuthUser getUserInfo(AuthUser authUser) {
        List<AuthUser> userList = authUserDao.queryAllByLimit(authUser);
        if (CollectionUtils.isEmpty(userList)) {
            return new AuthUser();
        }
        return userList.get(0);
    }

    @Override
    public List<AuthUser> listUserInfoByIds(List<String> userNameList) {
        List<AuthUser> userList = authUserDao.listUserInfoByIds(userNameList);
        if (CollectionUtils.isEmpty(userList)) {
            return Collections.emptyList();
        }
        return userList;
    }


}
